﻿using System;
using System.IO;
using System.Linq;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using Resn.WhuPub.BIL;
using System.Collections.Generic;
using Resn.WhuPub.DAL;
using Resn.WhuPub.DML;

namespace Resn.WhuPub.BLL
{
        /// <summary>
        /// 实现门类管理器的属性和方法
        /// </summary>
        public class CategoryManager:ICategoryManager
        {
                #region 字段

                private List<ISubject> _subjects;
                private List<IMajor> _majors;

                #endregion

                #region 属性

                private static CategoryManager _instance;
                

                /// <summary>
                /// 获取学校/公司管理器实例
                /// </summary>
                /// <value>
                /// 学校/公司管理器实例
                /// </value>
                public static CategoryManager Instance
                {
                        get { return  _instance??(_instance = new CategoryManager()); }
                }


                /// <summary>
                /// 获取门类集合
                /// </summary>
                /// <value>
                /// 门类集合
                /// </value>
                public List<ICategory> Categorys
                {
                        get
                        {
                                var models = DBStorage.Instance.Select<CategoryModel>();

                                var categorys = new List<ICategory>();

                                models.ForEach(i => categorys.Add(new Category(i)));

                                return categorys;
                        }
                }

                public List<ISubject> Subjects
                {
                        
                        get
                        {
                                if (_subjects == null)
                                {
                                        _subjects = new List<ISubject>();

                                        var models = DBStorage.Instance.Select<SubjectModel>();

                                        models.ForEach(i => _subjects.Add(new Subject(i)));

                                }

                                return _subjects;
                        }
                }

                public List<IMajor> Majors
                {
                        get 
                        {
                                if (_majors == null)
                                {
                                        _majors = new List<IMajor>();

                                        var models = DBStorage.Instance.Select<MajorModel>();

                                        models.ForEach(i => _majors.Add(new Major(i)));

                                }

                                return _majors;
                        }
                }

                #endregion

                #region 方法



                /// <summary>
                /// 创建门类
                /// </summary>
                /// <param name="name">名称</param>
                /// <param name="code">代码</param>
                /// <param name="categoryLevel">层次</param>
                /// <returns>
                /// 创建的门类对象
                /// </returns>
                public ICategory CreateCategory(string name, string code, CategoryLevel categoryLevel)
                {
                        var model = new CategoryModel
                        {
                                Id = Guid.NewGuid().ToString(),
                                Name = name,
                                Code = code,
                                CategoryLevel = categoryLevel.ToString()
                        };

                        return new Category(model);
                }


                

                /// <summary>
                /// 从EXCEL文件加载门类集合
                /// </summary>
                /// <param name="path">EXCEL文件路径</param>
                /// <returns>门类集合</returns>
                public Dictionary<ICategory, Dictionary<ISubject, List<IMajor>>> LoadCategorysFromExcel(string path)
                {
                        string[] r = Enum.GetNames(typeof (CategoryLevel));

                        if (!File.Exists(path))
                        {
                                throw new InvalidOperationException("文件不存在，无法加载");
                        }

                        var result = new Dictionary<ICategory, Dictionary<ISubject, List<IMajor>>>();

                        using (var fileStream = new FileStream(path, FileMode.Open))
                        {
                                var workBook = new HSSFWorkbook(fileStream);
                                var sheet = workBook.GetSheetAt(0);

                                var rowsCount = sheet.LastRowNum;
                                var columnsCount = sheet.GetRow(0).PhysicalNumberOfCells;

                                if (columnsCount < 7)
                                {
                                        throw new InvalidOperationException("列错误，无法导入");
                                }

                                if (rowsCount < 2)
                                {
                                        throw new InvalidOperationException("行错误，无法导入");
                                }

                                for (int i = 1; i < rowsCount; i++)
                                {
                                        IRow row = sheet.GetRow(i);

                                        int lastCellNum = row.LastCellNum;

                                        if (lastCellNum < 3)
                                        {
                                                continue;
                                        }

                                        string categoryName = row.Cells[1].StringCellValue;
                                        string subjectName = row.Cells[3].StringCellValue;
                                        string majorName = row.Cells[6].StringCellValue;
                                        string categoryCode = row.Cells[2].StringCellValue;
                                        string subjectCode = row.Cells[4].StringCellValue;
                                        string majorCode = row.Cells[5].StringCellValue;
                                        string level = row.Cells[0].StringCellValue;

                                        CategoryLevel categoryLevel;
                                        bool success = Enum.TryParse(level, out categoryLevel);
                                        if (!success)
                                        {
                                                throw new InvalidOperationException(i + "行门类层次错误，无法导入");
                                        }

                                        if (string.IsNullOrEmpty(categoryName))
                                        {
                                                throw new InvalidOperationException(i + "行门类名称错误，无法导入");
                                        }

                                        if (string.IsNullOrEmpty(subjectName))
                                        {
                                                throw new InvalidOperationException(i + "行科目名称错误，无法导入");
                                        }

                                        if (string.IsNullOrEmpty(majorName))
                                        {
                                                throw new InvalidOperationException(i + "行专业名称错误，无法导入");
                                        }

                                        ICategory category;
                                        if (result.Keys.Any(j => j.Name == categoryName))
                                        {
                                                category = result.Keys.Single(k => k.Name == categoryName);
                                        }
                                        else
                                        {
                                                category = CreateCategory(categoryName, categoryCode, categoryLevel);
                                                result.Add(category, new Dictionary<ISubject, List<IMajor>>());
                                        }

                                        ISubject subject;
                                        if (result[category].Keys.Any(j => j.Name == subjectName))
                                        {
                                                subject = result[category].Keys.Single(k => k.Name == subjectName);
                                        }
                                        else
                                        {
                                                subject = category.CreateSubject(subjectName, subjectCode);
                                                result[category].Add(subject, new List<IMajor>()); 
                                        }

                                        if (result[category][subject].Any(k => k.Name == majorName))
                                        {
                                                throw new InvalidOperationException(i + "行专业名称错误，无法导入");
                                        }

                                        var major = subject.CreateMajor(majorName, majorCode);

                                        result[category][subject].Add(major);
                                }
                        }

                        return result;
                }
                #endregion

                
        }
}